package com.battery.minapp.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.battery.common.enums.OrderTradeStateEnum;
import com.battery.common.enums.UsedAuthStateDescriptionEnum;
import com.battery.common.enums.UsedAuthStateEnum;
import com.battery.common.utils.Constants;
import com.battery.common.utils.wx.WxAPIV3AesUtil;
import com.battery.system.domain.AuthUsed;
import com.battery.system.domain.Order;
import com.battery.system.domain.RefundOrder;
import com.battery.system.service.battery.IAuthUsedService;
import com.battery.system.service.battery.IOrderService;
import com.battery.system.service.battery.IRefundOrderService;
import com.github.binarywang.wxpay.bean.notify.WxPayNotifyResponse;
import com.github.binarywang.wxpay.bean.notify.WxPayOrderNotifyResult;
import com.github.binarywang.wxpay.bean.notify.WxPayRefundNotifyResult;
import com.github.binarywang.wxpay.bean.result.WxPayOrderQueryResult;
import com.github.binarywang.wxpay.exception.WxPayException;
import com.github.binarywang.wxpay.service.WxPayService;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.math.BigDecimal;

@Controller
@RequestMapping("/wx")
public class WxNotifyController {


    private static Logger logger = LoggerFactory.getLogger(WxNotifyController.class);

    @Autowired
    private WxPayService wxService;

    @Autowired
    private IOrderService orderService;

    @Autowired
    private IAuthUsedService authUsedService;


    @Autowired
    private IRefundOrderService refundOrderService;


    /**
     * 支付回调通知处理
     *
     * @param xmlData
     * @return
     */
    @PostMapping("/notify/order")
    @ResponseBody
    public String parseOrderNotifyResult(@RequestBody String xmlData) {
        logger.info("【微信支付回调通知处理】内容->" + xmlData);
        WxPayOrderNotifyResult notifyResult = null;
        try {
            notifyResult = wxService.parseOrderNotifyResult(xmlData);
        } catch (WxPayException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail("ERROR");
        }
        if (notifyResult == null) {
            return WxPayNotifyResponse.fail("ERROR");
        }
        String out_trade_no = notifyResult.getOutTradeNo();
        String return_code = notifyResult.getReturnCode();
        String transaction_id = notifyResult.getTransactionId();

        if (!"SUCCESS".equals(return_code)) {
            return WxPayNotifyResponse.fail("支付返回异常");
        }
        Order order = orderService.selectByOutTradeNo(out_trade_no);
        if (order == null) {
            return WxPayNotifyResponse.fail("获取订单失败[" + out_trade_no + "]");
        }
        if (OrderTradeStateEnum.PAY_SUCCESS.getCode().intValue() == (order.getTradeState()) || OrderTradeStateEnum.REFUND_SUCCESS.getCode().intValue() == (order.getTradeState())) {
            // 订单状态支付成功，或者退款成功，则代表该笔订单已处理完毕
            return WxPayNotifyResponse.success("OK");
        }
        WxPayOrderQueryResult result = null;
        try {
            result = wxService.queryOrder(transaction_id, null);
        } catch (WxPayException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail("查询订单出错");
        }
        if (result == null) {
            return WxPayNotifyResponse.fail("查询订单出错");
        }
        if ("SUCCESS".equals(result.getReturnCode()) && "SUCCESS".equals(result.getResultCode()) && "SUCCESS".equals(result.getTradeState())) {
            logger.info("【微信支付回调通知处理】支付成功,开始处理业务");
            return orderService.wxPayNotifyOrder(order, transaction_id);
        }
        return WxPayNotifyResponse.fail("失败");
    }


    /**
     * 微信支付分 回调通知 （用户确认租借通知，用户支付成功通知）
     *
     * @param request
     * @return
     */
    @RequestMapping("/scoreCallBack")
    public ResponseEntity wxScoreCallBack(HttpServletRequest request) {
        try {
            InputStream inStream = request.getInputStream();
            ByteArrayOutputStream outSteam = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len = 0;
            while ((len = inStream.read(buffer)) != -1) {
                outSteam.write(buffer, 0, len);
            }
            outSteam.close();
            inStream.close();
            String resultStr = new String(outSteam.toByteArray(), "utf-8");
            logger.info("【微信支付分回调】内容->" + resultStr);
            if (StringUtils.isBlank(resultStr)) {
                return new ResponseEntity(HttpStatus.EXPECTATION_FAILED);
            }
            JSONObject resultObj = JSONObject.parseObject(resultStr);
            String event_type = resultObj.getString("event_type"); // 通知类型
            logger.info("【微信支付分回调】通知类型->" + event_type);
            JSONObject resourceObj = JSONObject.parseObject(resultObj.getString("resource"));
            String ciphertext = resourceObj.getString("ciphertext");
            String associated_data = resourceObj.getString("associated_data");
            String nonce = resourceObj.getString("nonce");
            byte[] key = Constants.wxMerchantApiV3Key.getBytes("UTF-8");
            WxAPIV3AesUtil aesUtil = new WxAPIV3AesUtil(key);
            String decryptToString = aesUtil.decryptToString(associated_data.getBytes("UTF-8"), nonce.getBytes("UTF-8"), ciphertext);
            logger.info("【微信支付分回调】解密消息->" + decryptToString);
            JSONObject decryptJsonObj = JSON.parseObject(decryptToString);
            if ("PAYSCORE.USER_CONFIRM".equals(event_type)) {
                // 用户确认成功通知
                String out_order_no = decryptJsonObj.getString("out_order_no"); // 商户服务订单号
                String state = decryptJsonObj.getString("state"); // 服务订单状态
                String state_description = decryptJsonObj.getString("state_description"); // 订单状态说明

                AuthUsed authUsed = authUsedService.selectByOutOrderNo(out_order_no);
                if (UsedAuthStateEnum.DOING.type.equals(state)) {
                    if (UsedAuthStateDescriptionEnum.USER_CONFIRM.type.equals(state_description)
                            && authUsed != null) {
                        // 用户点击率确认，可进行租借操作
                        logger.info("【微信支付分回调】用户点击率确认租借");
                        AuthUsed authUsedUpdate = new AuthUsed();
                        authUsedUpdate.setUsedId(authUsed.getUsedId());
                        authUsedUpdate.setState(state);
                        authUsedUpdate.setStateDescription(state_description);
                        authUsedService.updateByPrimaryKeySelective(authUsedUpdate);
                    }
                }
            }
            if ("PAYSCORE.USER_PAID".equals(event_type)) {
                BigDecimal total_amount = decryptJsonObj.getBigDecimal("total_amount").divide(new BigDecimal(100));
                String out_order_no = decryptJsonObj.getString("out_order_no"); // 商户服务订单号
                AuthUsed authUsed = authUsedService.selectByOutOrderNo(out_order_no);
                if (authUsed != null) {
                    if (total_amount.compareTo(BigDecimal.ZERO) == 0) {
                        logger.info("【微信支付分回调】用户支付金额为0");
                        // 用户0元结束订单, 用户租借费用为0元
                        authUsedService.wxfreeZeroPay(authUsed);
                    } else {
                        logger.info("【微信支付分回调】用户支付金额为" + total_amount);
                        JSONObject collectionJSON = decryptJsonObj.getJSONObject("collection");
                        authUsedService.wxfreePay(collectionJSON, authUsed);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseEntity(HttpStatus.EXPECTATION_FAILED);
        }
        return new ResponseEntity(HttpStatus.OK);
    }


    /**
     * 退款回调通知处理
     *
     * @param xmlData
     * @return
     */
    @PostMapping("/notify/refund")
    @ResponseBody
    public String parseRefundNotifyResult(@RequestBody String xmlData) {
        logger.info("【微信支付退款回调通知处理】内容->" + xmlData);
        WxPayRefundNotifyResult payRefundNotifyResult = null;
        try {
            payRefundNotifyResult = wxService.parseRefundNotifyResult(xmlData);
        } catch (WxPayException e) {
            e.printStackTrace();
            return WxPayNotifyResponse.fail("失败");
        }
        if (payRefundNotifyResult == null) {
            return WxPayNotifyResponse.fail("失败");
        }
        String return_code = payRefundNotifyResult.getReturnCode();
        if (!"SUCCESS".equals(return_code)) {
            return WxPayNotifyResponse.fail("回调异常");
        }
        WxPayRefundNotifyResult.ReqInfo reqInfo = payRefundNotifyResult.getReqInfo();
        if (reqInfo == null) {
            return WxPayNotifyResponse.fail("解密异常");
        }
        String out_refund_no = reqInfo.getOutRefundNo(); // 商户退款单号
        RefundOrder refundOrder = refundOrderService.selectByOutRefundNo(out_refund_no);
        if (refundOrder == null) {
            return WxPayNotifyResponse.fail("未查询到对应的退款订单");
        }
        refundOrderService.operationWxRefundNotify(refundOrder, reqInfo);
        return WxPayNotifyResponse.success("成功");
    }


}
